package wv;
import java.io.*; 
import java.util.*;

/**
 * A class to automatically calculate the mutation adequacy score for a set of
 * testsuites.
 * 
 * This class requires the following files in the source root.
 * 
 * - javalanche.xml
 * 		Javalanche config file. It must contain a reference to the location of
 * 		javalanche on the current system.
 * - build.xml
 * 		Ant build file. It must build the testsuites and the correct program.
 * 
 * @author Anna-Elisabeth Schnell, Arne Van der Stappen, Stefanie Verhulst
 *
 */
public class MutationTester {
	
	/**
	 * Calculate the MAS for a set of testsuites.
	 * The results will be outputted to the default output stream.
	 * 
	 * @param	testPackage
	 * 			The package containing all tests.
	 * @param	programPackage
	 * 			The package containing the programs to mutate.
	 * @param	classes
	 * 			The names of the testsuites to evaluate.
	 */
	public static void calculateMAS(String testPackage, String programPackage, List<String> classes) { 
		long startTime = System.currentTimeMillis();
		try { 
			Process p=Runtime.getRuntime().exec("cmd /c ant compile");
			clearInputStream(p);
			p.waitFor();

			for (String testclass : classes) {

			p=Runtime.getRuntime().exec("cmd /c ant -f javalanche.xml startHsql -Dtests="+testPackage+"."+testclass+" -Dprefix="+programPackage);
			
			p=Runtime.getRuntime().exec("cmd /c ant -f javalanche.xml schemaexport");
			clearInputStream(p);
			p.waitFor();
			
				p=Runtime.getRuntime().exec("cmd /c ant -f javalanche.xml -Dtests="+testPackage+"."+testclass+" -Dprefix="+programPackage+" scanProject");
				clearInputStream(p);
				p.waitFor();
				
				p=Runtime.getRuntime().exec("cmd /c ant -f javalanche.xml -Dtests="+testPackage+"."+testclass+" -Dprefix="+programPackage+" scan");
				clearInputStream(p);
				p.waitFor();

				//LOOP2: collect tasks:
				List<String> taskFiles = new ArrayList<String>();
				p=Runtime.getRuntime().exec("cmd /c ant -f javalanche.xml -Dtests="+testPackage+"."+testclass+" -Dprefix="+programPackage+" createTasks");

				BufferedReader reader=new BufferedReader(new InputStreamReader(p.getInputStream())); 
				String line=reader.readLine(); 
				while(line!=null) 
				{ 
					if (line.matches(".*Task created:.+")) {
						String[] parts = line.split("\\\\");
						taskFiles.add(parts[parts.length-1]);
					}
					line=reader.readLine(); 
				} 
				p.waitFor();

				//END LOOP2
				
				//LOOP3: for each task
				for (String taskFile : taskFiles) {
					p=Runtime.getRuntime().exec("cmd /c ant -f javalanche.xml -Dtests="+testPackage+"."+testclass+" -Dprefix=s"+programPackage+" runMutations -Dmutation.file=./mutation-files/"+taskFile);
					clearInputStream(p);
				}
				//END LOOP3
				
				
				p=Runtime.getRuntime().exec("cmd /c ant -f javalanche.xml -Dtests="+testPackage+"."+testclass+" -Dprefix="+programPackage+" analyzeResults");
				
				reader=new BufferedReader(new InputStreamReader(p.getInputStream())); 
				line=reader.readLine();
				while(line!=null) 
				{ 
					if (line.matches(".*Mutation score:.+")) {
						String[] parts = line.split(" ");
						String score = parts[parts.length-1];
						System.out.println(testclass+"\t"+score);
					}
					line=reader.readLine();
				}

				p=Runtime.getRuntime().exec("cmd /c ant -f javalanche.xml stopHsql -Dtests="+testPackage+"."+testclass+" -Dprefix="+programPackage);
			}
			p=Runtime.getRuntime().exec("cmd /c ant -f javalanche.xml stopHsql");
			clearInputStream(p);
			p.waitFor();
		}
		catch(IOException e1) {} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("Finished after: " + (System.currentTimeMillis() - startTime) );
			 
		System.out.println("Done"); 
	}
	
	/**
	 * Clear the inputstream to prevent an full buffer from blocking the process.
	 * 
	 * @param	p
	 * 			The process to clear the inputstream from.
	 */
	private static void clearInputStream(Process p) {
		BufferedReader reader=new BufferedReader(new InputStreamReader(p.getInputStream())); 
		String line;
		try {
			line = reader.readLine();
			while(line!=null) 
			{ 
				if (line.matches(".*BUILD SUCCESSFUL.*"))
					p.destroy();
				line=reader.readLine(); 
				
			} 
			reader=new BufferedReader(new InputStreamReader(p.getErrorStream())); 
			line = reader.readLine();
			while(line!=null) 
			{ 
				line=reader.readLine(); 
				
			}
		} catch (IOException e) {
			e.printStackTrace();
		} 
	}

}
